// struct
class Token {
    constructor(value, pos) {
        this.value = value
        this.pos = pos
    }
}
class Comment {
    constructor(value, pos) {
        this.value = value
        this.pos = pos
    }
}
class String {
    constructor(value, pos) {
        this.value = value
        this.pos = pos
    }
}
class Parenthesis {
    constructor(value, pos) {
        this.value = value
        this.pos = pos
    }
}

// comment and string
// ; comment
// "string"
function pass0(str) {
    let state = 0 // 0 normal, 1 in string, 2 in comment
    let i = 0
    let word = ""
    let pos = 0
    let ret = []
    for (let c of str) {
        if (state == 0) {
            if (c == ';') {
                if (word !== "") {
                    ret.push(new Token(word, pos))
                }
                word = c
                state = 2
                pos = i
            } else if (c == '"') {
                if (word !== "") {
                    ret.push(new Token(word, + pos))
                }
                word = c
                state = 1
                pos = i
            } else {
                word += c
            }
        } else if (state == 1) {
            if (c === '"') {
                word += c
                ret.push(new String(word, + pos))
                word = ""
                state = 0
                pos = i + 1
            } else {
                word += c
            }
        } else if (state == 2) {
            if (c == '\r' || c == '\n') {
                ret.push(new Comment(word, pos))
                word = c
                state = 0
                pos = i
            } else {
                word += c
            }
        }
        // console.log(c)
        i++
    }
    if (word !== "") {
        if (state === 0) {
            ret.push(new Token(word, pos))
        } else {
            ret.push(new Comment(word, pos))
        }
    }
    return ret
}
// pass string
function pass1(tklst) {
    return tklst
}

// for space and parentheses
function pass2(tklst) {
    let i = 0
    let ret = []
    for (let tk of tklst) {
        if (tk instanceof Token) {
            const tks = pass2_(tk.value, tk.pos)
            ret = ret.concat(tks)
        } else {
            ret.push(tk)
        }
        i++
    }
    return ret
}

function pass2_(str, posBegin) {
    let state = 0 // 0 normal, 1 in token
    let i = 0
    let word = ""
    let pos = 0
    let ret = []
    for (let c of str) {
        if (state == 0) {
            if (c == '(' || c == ')') {
                ret.push(new Parenthesis(c, posBegin + i))
                word = ""
                pos = i + 1
            } else if (isSpace(c)) {
                word = ""
                pos = i + 1
            } else {
                word = c
                pos = i
                state = 1
            }
        } else if (state == 1) {
            if (c == '(' || c == ')') {
                if (word !== "") {
                    ret.push(new Token(word, posBegin + pos))
                }
                ret.push(new Parenthesis(c, posBegin + i))
                word = ""
                state = 0
                pos = i + 1
            } else if (isSpace(c)) {
                if (word !== "") {
                    ret.push(new Token(word, posBegin + pos))
                }
                word = ""
                state = 0
                pos = i + 1
            } else {
                word += c
            }
        }
        // console.log(c)
        i++
    }
    if (word !== "") {
        if (state === 1) {
            ret.push(new Token(word, posBegin + pos))
        }
    }
    return ret
}
function isSpace(c) {
    return c === " " || c === "\r" || c === "\n" || c === "\t"
}
function token(str) {
    return pass2(pass0(str))
}
module.exports = { pass0, pass1, pass2, token, Token, Comment, String, Parenthesis };